﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using System.IO;

namespace PL_TileEditor
{
    public partial class MapViewer : ScrollableControl
    {
        public Size MapSize;
        public int[,,] TileMap = new int[3,32,32];
        public int ViewDepth;
        public Point SelectedTile = new Point(0,0);
        public TileViewer Tiles = null;
        public Point PrevMouse = new Point(0,0);
        public int SelectedLayer = 1;
        public bool[] ViewableLayers = new bool[3];
        public enum Tool { Pen, Eraser, Fill, Object, None };
        public Tool CurrentTool = Tool.Pen;
        public bool PlacingTiles = true;
        public bool ShowGrid = true;
        public List<BaseObject> ObjectList = new List<BaseObject>();
        public string SelectedObject;
        public BaseObject HoveringObject; // Oh god how did this get here? I am NOT good with computers!
 

        public MapViewer()
        {
            try
            {
                MapSize = new Size(32, 32);

                for (int z = 0; z < 3; z++)
                {
                    for (int x = 0; x < 32; x++)
                    {
                        for (int y = 0; y < 32; y++)
                        {
                            TileMap[z, x, y] = 9999;
                        }
                    }
                    ViewableLayers[z] = true;
                }

            }
            catch { }
            DoubleBuffered = true;
            ResizeRedraw = true;

            InitializeComponent();
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            //Invalidate(new Rectangle(new Point(Math.Min(e.X, PrevMouse.X) - Tiles.TileSize.Width, Math.Min(e.Y, PrevMouse.Y) - Tiles.TileSize.Height), new Size(Math.Max(e.X, PrevMouse.X) - Math.Min(e.X, PrevMouse.X), Math.Max(e.Y, PrevMouse.Y) - Math.Min(e.Y, PrevMouse.Y)) + Tiles.TileSize + Tiles.TileSize));
            Invalidate();

            base.OnMouseUp(e);
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            Point OldSelectedTile = SelectedTile;
            Focus();
            try
            {
                if (e.Button == MouseButtons.Left)
                {
                    if (CurrentTool == Tool.Pen)
                    {
                        SelectedTile = new Point((e.X - AutoScrollPosition.X) / Tiles.TileSize.Width, (e.Y - AutoScrollPosition.Y) / Tiles.TileSize.Height);

                        TileMap[SelectedLayer, SelectedTile.X, SelectedTile.Y] = Tiles.SelectedTile;

                    }
                    else if (CurrentTool == Tool.Fill)
                    {
                        SelectedTile = new Point((e.X - AutoScrollPosition.X) / Tiles.TileSize.Width, (e.Y - AutoScrollPosition.Y) / Tiles.TileSize.Height);

                        Fill(TileMap[SelectedLayer, SelectedTile.X, SelectedTile.Y], Tiles.SelectedTile, SelectedTile);

                        Invalidate(new Rectangle(new Point(0, 0), this.Size));
                        Update();
                    }
                    else if (CurrentTool == Tool.Eraser) 
                    {
                        SelectedTile = new Point((e.X - AutoScrollPosition.X) / Tiles.TileSize.Width, (e.Y - AutoScrollPosition.Y) / Tiles.TileSize.Height);

                        TileMap[SelectedLayer, SelectedTile.X, SelectedTile.Y] = 9999;
                    }
                    else if (CurrentTool == Tool.Object)
                    {
                        if (SelectedObject == "Portal")
                        {
                            Portal tempPort = new Portal();
                            tempPort.m_Position = new Point(e.X - AutoScrollPosition.X, e.Y - AutoScrollPosition.Y);
                            PortalViewer newWind = new PortalViewer();
                            newWind.ShowDialog();
                            tempPort.m_szEnd = newWind.DestMap;
                            tempPort.m_TriggerButton = newWind.TriggerButton;
                            tempPort.m_EndPosition = newWind.DestPoint;
                            if (newWind.DiagResult == DialogResult.OK)
                                ObjectList.Add(tempPort);
                            Invalidate(new Rectangle(tempPort.m_Position.X - 128, tempPort.m_Position.Y - 128, 256, 256));
                        }
                        else if (SelectedObject == "Enemy")
                        {
                            OpenFileDialog lol = new OpenFileDialog();
                            lol.Filter = "Enemy File | *.enm";
                            if (lol.ShowDialog() == DialogResult.OK)
                            {
                                Enemy newEnemy = new Enemy();
                                newEnemy.SetFile(Path.GetFileName(lol.FileName));
                                newEnemy.m_Position = new Point(e.X - AutoScrollPosition.X, e.Y - AutoScrollPosition.Y);
                                ObjectList.Add(newEnemy);
                                Invalidate(new Rectangle(newEnemy.m_Position.X - 128, newEnemy.m_Position.Y - 128, 256, 256));
                            }
                        }
                    }
                    else
                    {
                        SelectedTile = new Point((e.X - AutoScrollPosition.X) / Tiles.TileSize.Width, (e.Y - AutoScrollPosition.Y) / Tiles.TileSize.Height);
                    }
                }
                if (e.Button == MouseButtons.Right)
                {
                    if (CurrentTool == Tool.Object)
                    {
                        ObjectList.Remove(HoveringObject);
                    }
                }
            }
            catch { }

            if (OldSelectedTile != SelectedTile)
            {
                Invalidate(new Rectangle(new Point(Math.Min(e.X, PrevMouse.X) - Tiles.TileSize.Width, Math.Min(e.Y, PrevMouse.Y) - Tiles.TileSize.Height), new Size(Math.Max(e.X, PrevMouse.X) - Math.Min(e.X, PrevMouse.X), Math.Max(e.Y, PrevMouse.Y) - Math.Min(e.Y, PrevMouse.Y)) + Tiles.TileSize + Tiles.TileSize));
            }

            PrevMouse = new Point(e.X, e.Y);

            base.OnMouseDown(e);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            if (Tiles != null)
            {
                System.Drawing.Imaging.ImageAttributes ia = new System.Drawing.Imaging.ImageAttributes();
                //ia.SetColorKey(Color.FromArgb(128, 0, 0, 0), Color.FromArgb(128, 255, 255, 255), System.Drawing.Imaging.ColorAdjustType.Default);
                System.Drawing.Imaging.ColorMatrix cm = new System.Drawing.Imaging.ColorMatrix();
                cm.Matrix00 = cm.Matrix11 = cm.Matrix22 = 1.0f;
                cm.Matrix33 = 0.5f;
                //ia.SetColorMatrix(cm);
                for (int z = 0; z < 3; z++)
                {
                    if (ViewableLayers[z] == false)
                        continue;
                    for (int x = (-AutoScrollPosition.X / Tiles.TileSize.Width); (x < MapSize.Width && x <= ((-AutoScrollPosition.X + Width) / Tiles.TileSize.Width)); x++)
                    {
                        for (int y = (-AutoScrollPosition.Y / Tiles.TileSize.Height); (y < MapSize.Height && y <= ((-AutoScrollPosition.Y + Height) / Tiles.TileSize.Height)); y++)
                        {
                            if (TileMap[z, x, y] != 9999)
                            {
                                Rectangle RECT1 = new Rectangle(x * Tiles.TileSize.Width + AutoScrollPosition.X, y * Tiles.TileSize.Height + AutoScrollPosition.Y, Tiles.TileSize.Width, Tiles.TileSize.Height);
                                Rectangle RECT2 = new Rectangle((TileMap[z, x, y]) % (Tiles.TileImage.Width / Tiles.TileSize.Width) * Tiles.TileSize.Width,
                                                    (TileMap[z, x, y]) / (Tiles.TileImage.Width / Tiles.TileSize.Width) * Tiles.TileSize.Height,
                                                    Tiles.TileSize.Width, Tiles.TileSize.Height);
                                e.Graphics.DrawImage(Tiles.TileImage, RECT1, RECT2.X, RECT2.Y, RECT2.Width, RECT2.Height, GraphicsUnit.Pixel, ia);

                            }
                            if (CurrentTool == Tool.None && x == SelectedTile.X && y == SelectedTile.Y)
                            {
                                e.Graphics.DrawRectangle(Pens.White, new Rectangle(x * Tiles.TileSize.Width + AutoScrollPosition.X + 1, y * Tiles.TileSize.Height + AutoScrollPosition.Y + 1, Tiles.TileSize.Width - 2, Tiles.TileSize.Height - 2));
                                e.Graphics.DrawRectangle(Pens.Black, new Rectangle(x * Tiles.TileSize.Width + AutoScrollPosition.X + 2, y * Tiles.TileSize.Height + AutoScrollPosition.Y + 2, Tiles.TileSize.Width - 3, Tiles.TileSize.Height - 3));
                            }
                            //else
                            if (ShowGrid == true)
                                e.Graphics.DrawRectangle(Pens.Black, new Rectangle(x * Tiles.TileSize.Width + AutoScrollPosition.X, y * Tiles.TileSize.Height + AutoScrollPosition.Y, Tiles.TileSize.Width, Tiles.TileSize.Height));
                            //e.Graphics.DrawString(x.ToString() + "," + y.ToString(), Font, Brushes.Black, new PointF(x * TileSize.Width + AutoScrollPosition.X, y * TileSize.Height + AutoScrollPosition.Y));


                        }
                    }
                }

                foreach (BaseObject b in ObjectList) 
                {
                    b.Render(e, AutoScrollPosition);
                }
            }

            base.OnPaint(e);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            HoveringObject = null;
            Point OldSelectedTile = SelectedTile;
            try
            {
                if (e.Button == MouseButtons.Left)
                {
                    if (CurrentTool == Tool.Pen)
                    {
                        SelectedTile = new Point((e.X - AutoScrollPosition.X) / Tiles.TileSize.Width, (e.Y - AutoScrollPosition.Y) / Tiles.TileSize.Height);

                        TileMap[SelectedLayer, SelectedTile.X, SelectedTile.Y] = Tiles.SelectedTile;
                    }
                    else if (CurrentTool == Tool.Fill)
                    {
                        SelectedTile = new Point((e.X - AutoScrollPosition.X) / Tiles.TileSize.Width, (e.Y - AutoScrollPosition.Y) / Tiles.TileSize.Height);

                        Fill(TileMap[SelectedLayer, SelectedTile.X, SelectedTile.Y], Tiles.SelectedTile, SelectedTile);

                        Invalidate(new Rectangle(new Point(0, 0), this.Size));
                        Update();
                    }
                    else if (CurrentTool == Tool.Eraser)
                    {
                        SelectedTile = new Point((e.X - AutoScrollPosition.X) / Tiles.TileSize.Width, (e.Y - AutoScrollPosition.Y) / Tiles.TileSize.Height);

                        TileMap[SelectedLayer, SelectedTile.X, SelectedTile.Y] = 9999;
                    }
                    else
                    {
                        SelectedTile = new Point((e.X - AutoScrollPosition.X) / Tiles.TileSize.Width, (e.Y - AutoScrollPosition.Y) / Tiles.TileSize.Height);
                    }
                    
                }
                if (e.Button == MouseButtons.Right)
                {

                }
                if (CurrentTool == Tool.Object)
                {
                    foreach (BaseObject b in ObjectList)
                    {
                        if (new Rectangle(e.X - 3 - AutoScrollPosition.X, e.Y - 3 - AutoScrollPosition.Y, 6, 6).IntersectsWith(new Rectangle(b.m_Position.X - 32, b.m_Position.Y - 32, 64, 64)))
                        {
                            HoveringObject = b;
                        }
                    }
                }
            }
            catch { }

            if (OldSelectedTile != SelectedTile)
            {
                Invalidate(new Rectangle(new Point(Math.Min(e.X, PrevMouse.X) - Tiles.TileSize.Width, Math.Min(e.Y, PrevMouse.Y) - Tiles.TileSize.Height), new Size(Math.Max(e.X,PrevMouse.X)-Math.Min(e.X, PrevMouse.X), Math.Max(e.Y,PrevMouse.Y)-Math.Min(e.Y, PrevMouse.Y)) + Tiles.TileSize + Tiles.TileSize));
            }

            PrevMouse = new Point(e.X, e.Y);
            
            base.OnMouseMove(e);
        }

        protected override void OnScroll(ScrollEventArgs se)
        {
            Invalidate(new Rectangle(new Point(0, 0), this.Size));
            Update();
            
            base.OnScroll(se);
        }

        public void ChangeSize(Size NewSize)
        {
            try
            {
                Size OldSize = MapSize;

                MapSize.Width = NewSize.Width;
                MapSize.Height = NewSize.Height;

                int[, ,] tempMap = new int[3, NewSize.Width, NewSize.Height];

                for (int z = 0; z < 3; z++)
                {
                    for (int x = 0; x < NewSize.Width; x++)
                    {
                        for (int y = 0; y < NewSize.Height; y++)
                        {
                            tempMap[z, x, y] = 9999;
                        }
                    }
                }

                for (int x = 0; x < Math.Min(NewSize.Width, OldSize.Width); x++)
                {
                    for (int y=0; y<Math.Min(NewSize.Height, OldSize.Height); y++) {
                        tempMap[0, x, y] = TileMap[0, x, y];
                        tempMap[1, x, y] = TileMap[1, x, y];
                        tempMap[2, x, y] = TileMap[2, x, y];
                    }
                }

                TileMap = tempMap;

                AutoScrollMinSize = new Size(MapSize.Width * Tiles.TileSize.Width, MapSize.Height * Tiles.TileSize.Height);
                
            }
            catch { }
            Invalidate(new Rectangle(new Point(0, 0), this.Size));
        }

        public void Fill(int tileID, int newTileID, Point coord)
        {
            if (tileID == newTileID)
                return;

            for (int y = -1; y < 2; y++)
            {
                if (y + coord.Y < 0 || y + coord.Y >= MapSize.Height)
                    continue;

                if (TileMap[SelectedLayer, coord.X, y + coord.Y] == tileID)
                {
                    TileMap[SelectedLayer, coord.X, y + coord.Y] = newTileID;
                    Fill(tileID, newTileID, new Point(coord.X, y + coord.Y));
                }
            }

            for (int x = -1; x < 2; x++)
            {
                if (x + coord.X < 0 || x + coord.X >= MapSize.Width)
                    continue;

                if (TileMap[SelectedLayer, x + coord.X, coord.Y] == tileID)
                {
                    TileMap[SelectedLayer, x + coord.X, coord.Y] = newTileID;
                    Fill(tileID, newTileID, new Point(x + coord.X, coord.Y));
                }
            }
            
        }
    }
}
